home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / dev / c / vbcc.lha / vbcc / pasm / output_ehf.c < prev    next >
C/C++ Source or Header  |  1998-02-17  |  11KB  |  387 lines

  1. /* $VER: pasm output_ehf.c V0.7 (02.01.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.7 (02.01.98) phx
  16.  *      Sections after a section with HUNK_EXT were 4 bytes too large.
  17.  *      Output format OFMT_ADOS support. The difference between ADOS and
  18.  *      and EHF is, that ADOS uses HUNK_CODE instead HUNK_PPC_CODE and
  19.  *      doesn't support any PPC-specific relocations and references types.
  20.  *      This makes it possible to link simple PowerPC programs with an
  21.  *      old linker, like BLink, SLink or PhxLnk.
  22.  * v0.4 (02.07.97) phx
  23.  *      File created.
  24.  */
  25.  
  26.  
  27. #define OUTPUT_EHF_C
  28. #include "ppcasm.h"
  29. #include "ehf.h"
  30.  
  31.  
  32. struct XRefNode {
  33.   struct node n;
  34.   char *sym_name;
  35.   uint8 ref_type;
  36.   int noffsets;
  37.   struct list xreflist;
  38. };
  39.  
  40.  
  41. static char *output_name;
  42. static int nsecs = 0;
  43. static bool exthunk;
  44.  
  45.  
  46. void output_ehf(struct GlobalVars *);
  47.  
  48. static void reloc_hunk(FILE *,struct Section *,uint8,uint32);
  49. static void unsupp_relocs(struct Section *);
  50. static void ext_header(FILE *);
  51. static void ext_refs(FILE *,struct GlobalVars *,struct Section *);
  52. static void ext_defs(FILE *,struct GlobalVars *,uint32,uint8,uint32);
  53. static uint32 word_strlen(char *);
  54. static void write_name(FILE *,struct GlobalVars *,char *);
  55. static void fwalign(FILE *,struct GlobalVars *,uint32);
  56. static void fw(FILE *,void *,size_t);
  57. static void fw4(FILE *,uint32);
  58.  
  59.  
  60.  
  61. void output_ehf(struct GlobalVars *gv)
  62. {
  63.   struct Section *nextsec,*sec=(struct Section *)gv->sectionlist.first;
  64.   struct Symbol *symchain;
  65.   uint32 index;
  66.   bool ehfmode = gv->output==OFMT_EHF;
  67.   FILE *fp;
  68.  
  69.   /* assign an index to each valid section */
  70.   while (nextsec = (struct Section *)sec->n.next) {
  71.     if (!(sec->flags & SF_DISCARD) && sec->size > 0)
  72.       sec->index = nsecs++;
  73.     sec = nextsec;
  74.   }
  75.  
  76.   /* create output file */
  77.   output_name = gv->dest_name;
  78.  
  79.   if (fp = fopen(output_name,"w")) {  /* create output file */
  80.     fw4(fp,HUNK_UNIT);
  81.     if (gv->ident) {
  82.       fw4(fp,word_strlen(gv->ident));  /* unit name */
  83.       write_name(fp,gv,gv->ident);
  84.     }
  85.     else
  86.       fw4(fp,0);
  87.  
  88.  
  89.     /* section loop */
  90.     sec = (struct Section *)gv->sectionlist.first;
  91.     while (nextsec = (struct Section *)sec->n.next) {
  92.       exthunk = FALSE;
  93.       if (!(sec->flags & SF_DISCARD) && sec->size > 0) {
  94.         index = sec->index;
  95.  
  96.         /* section name */
  97.         fw4(fp,HUNK_NAME);
  98.         fw4(fp,word_strlen(sec->name));
  99.         write_name(fp,gv,sec->name);
  100.  
  101.         /* section type and size */
  102.         switch(sec->type) {
  103.           case ST_CODE:
  104.             ehfmode ? fw4(fp,HUNK_PPC_CODE) : fw4(fp,HUNK_CODE);
  105.             break;
  106.           case ST_DATA:
  107.             fw4(fp,HUNK_DATA);
  108.             break;
  109.           case ST_UDATA:
  110.             fw4(fp,HUNK_BSS);
  111.             break;
  112.           default:  /* section type not supported in EHF/ADOS */
  113.             error(52,sec->name,(int)sec->type);
  114.             fw4(fp,HUNK_DATA);  /* defaults to HUNK_DATA */
  115.             break;
  116.         }
  117.         fw4(fp,(uint32)(sec->size+3)>>2);
  118.  
  119.         /* write section contents */
  120.         if (!(sec->flags & SF_UNINITIALIZED)) {
  121.           fw(fp,sec->contents,(uint32)sec->size);
  122.           fwalign(fp,gv,(uint32)sec->size);
  123.         }
  124.  
  125.         /* relocation hunks */
  126.         reloc_hunk(fp,sec,R_PPC_ADDR32,HUNK_ABSRELOC32);
  127. /* @@@  reloc_hunk(fp,sec,R_PPC_ADDR16,HUNK_ABSRELOC16); */
  128.         if (ehfmode)
  129.           reloc_hunk(fp,sec,R_PPC_REL24,HUNK_RELRELOC26);
  130.         reloc_hunk(fp,sec,R_PPC_REL14,HUNK_RELRELOC16);
  131.         reloc_hunk(fp,sec,R_PPC_REL14_BRTAKEN,HUNK_RELRELOC16);
  132.         reloc_hunk(fp,sec,R_PPC_REL14_BRNTAKEN,HUNK_RELRELOC16);
  133.         reloc_hunk(fp,sec,R_PPC_REL32,HUNK_RELRELOC32);
  134.         reloc_hunk(fp,sec,R_PPC_TOC16,HUNK_DREL16);
  135.         unsupp_relocs(sec);  /* print unsupported relocations */
  136.  
  137.         /* external references and global definitions */
  138.         ext_refs(fp,gv,sec);
  139.         ext_defs(fp,gv,index,SYM_RELOC,EXT_DEF);
  140.         if (index == 0)  /* put absolute definitions in first HUNK_EXT */
  141.           ext_defs(fp,gv,0xffff,SYM_ABS,EXT_ABS);
  142.         if (exthunk)
  143.           fw4(fp,0);  /* close HUNK_EXT block */
  144.  
  145.         /* symbol table */
  146.         ext_defs(fp,gv,index,SYM_RELOC,EXT_SYMB);
  147.  
  148.         fw4(fp,HUNK_END);  /* end of this hunk */
  149.       }
  150.       sec = nextsec;
  151.     }
  152.  
  153.     fclose(fp);
  154.   }
  155.   else
  156.     error(25,output_name);  /* unable to create output file */
  157. }
  158.  
  159.  
  160. static void reloc_hunk(FILE *fp,struct Section *sec,uint8 r,uint32 ehfrel)
  161. /* generate an EHF relocation hunk for a specific reloc type */
  162. {
  163.   struct Reloc *nextrel,*rel=(struct Reloc *)sec->reloclist.first;
  164.   struct list **rlist=alloc(nsecs*sizeof(struct list *));
  165.   int *rcnt=alloczero(nsecs*sizeof(int));  /* reloc cnt for all sections */
  166.   bool hunk_required=FALSE;
  167.   int i;
  168.  
  169.   for (i=0; i<nsecs; i++) {  /* empty reloc lists for each section */
  170.     rlist[i] = alloc(sizeof(struct list));
  171.     initlist(rlist[i]);
  172.   }
  173.  
  174.   while (nextrel = (struct Reloc *)rel->n.next) {
  175.     if (rel->type == r) {
  176.       /* move reloc node of correct type into relocssect's rlist */
  177.       remnode(&rel->n);
  178.       addtail(rlist[rel->relocsect->index],&rel->n);
  179.       rcnt[rel->relocsect->index]++;
  180.       hunk_required = TRUE;
  181.     }
  182.     rel = nextrel;
  183.   }
  184.  
  185.   if (hunk_required) {  /* there's at least one relocation */
  186.     fw4(fp,ehfrel);  /* reloc hunk id */
  187.     for (i=0; i<nsecs; i++) {
  188.       if (rcnt[i]) {
  189.         fw4(fp,(uint32)rcnt[i]);  /* number of relocations */
  190.         fw4(fp,(uint32)i);  /* section index */
  191.  
  192.         /* store relocation offsets */
  193.         while(rel = (struct Reloc *)remhead(rlist[i])) {
  194.           fw4(fp,(uint32)rel->offset);
  195.           free(rel);
  196.         }
  197.       }
  198.     }
  199.     fw4(fp,0);  /* no more relocation entries */
  200.   }
  201.  
  202.   /* free dynamically allocated rlists and rcnt array */
  203.   for (i=0; i<nsecs; free(rlist[i++]));
  204.   free(rcnt);
  205. }
  206.  
  207.  
  208. static void unsupp_relocs(struct Section *sec)
  209. {
  210.   struct Reloc *nextrel,*rel=(struct Reloc *)sec->reloclist.first;
  211.  
  212.   while (nextrel = (struct Reloc *)rel->n.next) {
  213.     error(53,elfrel_name[rel->type & ELFRELNAMMSK],rel->offset,sec->name);
  214.     rel = nextrel;
  215.   }
  216. }
  217.  
  218.  
  219. static void ext_header(FILE *fp)
  220. {
  221.   if (!exthunk) {
  222.     exthunk = TRUE;
  223.     fw4(fp,HUNK_EXT);
  224.   }
  225. }
  226.  
  227.  
  228. static void ext_refs(FILE *fp,struct GlobalVars *gv,struct Section *sec)
  229. {
  230.   struct list xnodelist;  /* xrefs with same ref. type and symbol name */
  231.   struct XRefNode *xn,*nextxn;
  232.   struct XReference *xref;
  233.  
  234.   initlist(&xnodelist);
  235.   while (xref = (struct XReference *)remhead(&sec->xreflist)) {
  236.     char *name = xref->xsymbol->name;  /* name of xref'ed symbol */
  237.     uint8 rtype = xref->type;
  238.  
  239.     /* ELF32 -> EHF reference type mapping */
  240.     switch (rtype) {
  241.       case R_PPC_ADDR32:
  242.         rtype = EXT_ABSREF32;
  243.         break;
  244.       case R_PPC_REL14:
  245.       case R_PPC_REL14_BRTAKEN:
  246.       case R_PPC_REL14_BRNTAKEN:
  247.       case R_PPC_ADDR16:
  248.         rtype = EXT_RELREF16;
  249.         break;
  250.       case R_PPC_TOC16:
  251.         rtype = EXT_DEXT16;  /* small data */
  252.         break;
  253.       case R_PPC_REL24:
  254.         if (gv->output == OFMT_EHF) {
  255.           rtype = EXT_RELREF26;
  256.           break;
  257.         }
  258.       default:
  259.         error(53,elfrel_name[rtype & ELFRELNAMMSK],xref->offset,sec->name);
  260.         rtype = EXT_RELREF8;  /* @@@ to keep the loop running */
  261.         break;
  262.     }
  263.  
  264.     /* search appropriate XRefNode for referenced symbol and type */
  265.     xn = (struct XRefNode *)xnodelist.first;
  266.     while (nextxn = (struct XRefNode *)xn->n.next) {
  267.       if (!strcmp(name,xn->sym_name) && rtype==xn->ref_type)
  268.         break;
  269.       xn = nextxn;
  270.     }
  271.  
  272.     if (nextxn==NULL) {  /* we have to create a new XRefNode? */
  273.       xn = alloc(sizeof(struct XRefNode));
  274.       xn->sym_name = name;
  275.       xn->ref_type = rtype;
  276.       xn->no